<?php
ArrowController::importModel("project.ArrowSettings");
ArrowController::importModel("project.ArrowProjectsException");
ArrowController::importModel("beans.ArrowBeansStructure");
ArrowController::importModel("containers.ArrowContainersList");
ArrowController::importModel("resources.ArrowResources");
ArrowController::importModel("templatesSystem.templates.ArrowTemplatesStructure");
/**
 * Arrow project class
 * 
 * @version 1.0
 * @license  GNU GPL
 * @author Artur Kmera <artur.kmera@arrowplatform.org> 
 */
class ArrowProject implements ArrayAccess, IArrowSerializable, IArrowCacheable {

	/**
	 * Project conf file name
	 */
	const PROJECT_GLOBAL_CONF_FILE = "/conf/project-global-conf.xml";
	const PROJECT_CONF_FILE = "/conf/project-conf.xml";
	const BEANS_CONF = "/conf/beans-list.xml";
	const TEMPLATES_CONF = "/conf/templates-list.xml";
	const TEMPLATES_SCHEMAS_CONF = "/conf/schemas-list.xml";
	const CONTAINERS_CONF = "/conf/containers-list.xml";
		
	const ISessionHandler = "sessionHandler";	
	const IAuthHandler =  "authHandler";
	const IAccessHandler =  "accessHandler";
	const IExceptionHandler = "exceptionHandler";
	const IRemoteResponseHandler = "remoteResponseHandler";	
	
	const PATH = "./application" ;
	/**
	 * Handle for config document
	 * 
	 * @var simpleXML
	 */
	private $xmlConfDoc = null;

	/**
	 * Project configuration array
	 *
	 * @var array
	 */
	private $configuration;
	
	/**
	 * Defalut page class
	 *
	 * @var integer
	 */
	private $defaultPageClass;

	/**
	 * Reaction on error ( display | rediect )
	 *
	 * @var integer
	 */
	private $errorOnError = "display";

	/**
	 * Error display level (none|low|medium|high|strict)
	 *
	 * @var integer
	 */
	private $errorDisplayLevel = "all";

	/**
	 * Error log level (none|low|medium|high|strict)
	 *
	 * @var integer
	 */
	private $errorLogLevel = "high";

	/**
	 * ActionDescriptor constructor
	 *
	 * @param integer $id
	 * @param string $name
	 * @param string $path
	 * @param boolean $isDefault
	 */
	public function __construct( ) {
		
		$confFile = self::PATH . "/" . self :: PROJECT_CONF_FILE;
		$cacheFile = ArrowCacheProvider::getFileCache( $this, $confFile,  array( "file_prefix" => "project_config" )  );
		
		require_once $cacheFile;
		
		$this->errorDisplayLevel = $cache["errorDisplayLevel"] ;
		$this->errorLogLevel = $cache["errorLogLevel"] ;
		$this->errorOnError = $cache["errorOnError"] ;
		unset( $cache["errorDisplayLevel"] ) ;
		unset( $cache["errorLogLevel"] ) ;
		unset( $cache["errorOnError"] ) ;
		
		$this->configuration = $cache;
	
		ArrowSettings::initialize( $this, $this->configuration["settings"] ) ;
	
		$this->configuration["settings"] = ArrowSettings::getDefault() ;
		
		
		
	}
	
	/**
	 * (non-PHPdoc)
	 * @see core/IArrowCacheable#generateCache()
	 */
	public function generateCache($params){
		$tmp = array();
		$projectConf = $this->getXmlConfDocument();

		//$globalConf = $this->getXmlGlobalConfDocument() ;    // cacheing global sets
		//$globalCache = ArrowSettings::getDefault()->generateCache( $globalConf ) ;
		
		$tmp["settings"] = ArrowSettings::getDefault()->generateCache( $projectConf->settings->section ); 	//array_merge( $globalCache, ArrowSettings::getDefault()->generateCache( $projectConf->settings->section ) ) ;
		
		$tmp["handlers"] = array();
		foreach( $projectConf->handlers->handler as $handler )
			$tmp["handlers"][ (string) $handler->name ] = (string) $handler->model;
			
		$tmp["errorOnError"] = $tmp["settings"]["arrow"]["on_error"];
		$tmp["errorDisplayLevel"] = $tmp["settings"]["arrow"]["error_display_level"];
		$tmp["errorLogLevel"] = $tmp["settings"]["arrow"]["error_log_level"];

		//$packagesDir = $this->path.self::PACKAGES_DIR;
		//$tmp["packages"] = array();
		/*foreach( new DirectoryIterator( $packagesDir ) as $dir  ){
			$name = $dir."";
			if(!$dir->isDot() && $dir->isDir() && $name != ".svn" && $name[0] != "_"){
				$packageConf = simplexml_load_file($dir->getPathname()."/"."package.xml");
				$tmp["packages"]["".$packageConf->id] = array(
					"name" => "".$packageConf->name,
					"dir" => $dir->getPathname()				
				);
			}
		}*/
		return $tmp;
	}
	

	/**
	 * Saves changed project data (Persistent interface)
	 * 
	 * @return void
	 */
	public function doSave() {
		$projectConf = $this->getXmlConfDocument();
		
		$dom = new DOMDocument('1.0');
		$dom->preserveWhiteSpace = false;
		$dom->formatOutput = true;
		$dom->loadXML($projectConf->asXML());
		$project_conf_content = $dom->saveXML();

		$global = simplexml_load_string( '<?xml version="1.0"?><settings></settings>' ) ;
		
		$dom2 = new DOMDocument('1.0');
		$dom2->preserveWhiteSpace = false;
		$dom2->formatOutput = true;
		$dom2->loadXML($global->asXML());
		$project_global_content = $dom2->saveXML();
		
		file_put_contents( self::PATH . "/" . self :: PROJECT_CONF_FILE, $project_conf_content );
		file_put_contents( self::PATH . "/" . self :: PROJECT_GLOBAL_CONF_FILE, $project_global_content );
	}


	/**
	 * Get xml-conf document - read conf document from project conf file
	 *
	 * @return simpleXMLElement
	 */
	private function getXmlConfDocument( ) {
		if( $this->xmlConfDoc == null )
			$this->xmlConfDoc = simplexml_load_file( self::PATH. "/" . self :: PROJECT_CONF_FILE);
		return $this->xmlConfDoc;
	}
	
	private function getXmlGlobalConfDocument( ) {
		return	$this->xmlConfDoc = simplexml_load_file( self::PATH . "/" . self :: PROJECT_GLOBAL_CONF_FILE);
	}
	
	/**
	 * Returns proect default flag
	 *
	 * @return string
	 */
	public function isDefault() {
		return $this->isDefault;
	}

	/**
	 * Returns on error reaction
	 *
	 * @return string
	 */
	public function getErrorOnError() {
		return $this->errorOnError ;
	}

	/**
	 * Returns Error display level
	 *
	 * @return string
	 */
	public function getErrorDisplayLevel() {
		return $this->errorDisplayLevel ;
	}

	/**
	 * Returns Error log level
	 *
	 * @return string
	 */
	public function getErrorLogLevel() {
		return $this->errorLogLevel ;
	}
	
	
	/**
	 * Return all configuration variables
	 *
	 * @return array
	 */
	public function getSettings(){
		return $this->configuration["settings"];
	}
	
	public function getSetting( $setting_name ) {
		return $this->configuration["settings"]->getSetting( $setting_name ) ;
	}
	
	/**
	 * Returns xml config 
	 * 
	 * @param String $configType Type like ArrowProject::BEANS_CONF
	 * @return SimpleXMLElement
	 */
	public function getXMLConfig( $configType ){
		return simplexml_load_file(self::PATH.$configType);
	}
	
	public function saveXMLConfig( $configType, $xmlDoc ){
		$dom = new DOMDocument('1.0');
        $dom->preserveWhiteSpace = false;
        $dom->formatOutput = true;
        $dom->loadXML($xmlDoc->asXml());
        file_put_contents( self::PATH.$configType, $dom->saveXML());
	}
	
	/**
	 * Returns project specyfy job handler
	 * 
	 * @return Object
	 */
	public function getHandler( $handler ){
		$handler = $this->configuration["handlers"][$handler];
		return ArrowController::getModelInstance($handler);
	}

	/**
	 * Sets on error reaction ( display|redirect )
	 *
	 * @param String $reaction
	 * @return void
	 */
	public function setOnError( $reaction ) {
		$this->errorOnError = $reaction;
	}

	/**
	 * Sets error display level
	 *
	 * @param String $level 
	 * @return void
	 */
	public function setErrorDisplayLevel($level) {
		$this->errorDisplayLevel = $level;
	}

	/**
	 * Sets error log level
	 *
	 * @param String $level
	 * @return void
	 */
	public function setErrorLogLevel($level) {
		$this->errorLogLevel = $level;
	}



	/**
	 * ArrayAcces implementaction
	 * 
	 * @param string $key
	 * @return boolean
	 */
	public function offsetExists($key) {
		if (isset ($this->$key))
			return true;
		return false;
	}

	/**
	 * ArrayAcces implementaction
	 * 
	 * @param string $key
	 * @return mixed
	 */
	public function offsetGet($key) {
		if ($this->offsetExists($key)) {
			return $this->$key;
		} else {
			throw new ArrowCoreException(array (
				"msg" => "Offset doesn't exist'",
				"offset" => $key
			),0);
		}
	}

	/**
	 * ArrayAcces implementaction
	 * 
	 * @param string $key
	 * @param mixed value
	 */
	public function offsetSet($key, $value) {

		switch ($key) {
			case "errorOnError" :
				$this->setOnError( $value );	
			break;	
			case "errorDisplayLevel" :
				$this->setErrorDisplayLevel( $value );	
			break;	
			case "errorLogLevel" :
				$this->setErrorLogLevel( $value );	
			break;																
			default :
				throw new ArrowProjectsException(array (
					"msg" => "Incorect porpety set.",
					"porpety" => $key,
					"porpetyVal" => $value
				));			
			break;
		}
	}

	/**
	 * ArrayAcces implementaction
	 * 
	 * @param string $key
	 * @return mixed
	 */
	public function offsetUnset($key) {
		throw new ArrowActionsException(array (
			"msg" => "Can't use Array acces to unset action value'"
		));
	}

	/**
	 * IObjectSerialize implementaction
	 * 
	 * @return array Object in array
	 */
	public function serialize() {
		$val = array ();
		$val["id"] = $this->getId();
		$val["name"] = $this->getName();
		$val["isDefault"] = $this->isDefault();
		$val["errorOnError"] = $this->getOnError();
		$val["errorDisplayLevel"] = $this->getErrorDisplayLevel();
		$val["errorLogLevel"] = $this->getErrorLogLevel();
		return $val;
	}
	
	public function unserialize() {
		
		
	}
	
	/**
	 * Returns packages conf aray
	 * 
	 * @return array
	 */
	public function getPackagesConf(){
		return $this->configuration["packages"];
	}
	
	/**
	 * Check is package exists
	 * 
	 * @param string $packageId
	 * @return bool
	 */
	public function isPackageExist($packageId){
		return isset($this->configuration["packages"][$packageId]);
	}
	
	/**
	 * Returns handle for actions structure
	 * 
	 * @return ArrowBeansStructure
	 */
	public function getBeansStructure(){
		return ArrowBeansStructure::getDefault( $this );	
	}
	
	/**
	 * Returns handle for templates structure
	 * 
	 * @return ArrowTemplatesStructure
	 */
	public function getTemplatesStructure(){
		return ArrowTemplatesStructure::getDefault( $this  );	
	}
	
	/**
	 * Returns access manager
	 * 
	 * @return ArrowAccessManager
	 */
	public function getAccessManager(){
		return ArrowController::getDefault()->getAccessHandler() ;	
	}	
	
	/**
	 * Returns handle for Cointainers list
	 * 
	 * @return ArrowCointainersList
	 */
	public function getContainersList(){
		return ArrowContainersList::getDefault($this);
	}
	
	/**
	 * Returns handle for resources
	 * 
	 * @return ArrowResources
	 */
	public function getResources(){
		return ArrowResources::getDefault($this);
	}
	
}

?>